<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <img id="testImg" src="" alt="">
    <script>
        // 同步
        // 同步和异步是一种消息通知机制
        // 有阻塞

        // 异步
        // 没有阻塞
        // 异步任务处理:回调
        // 在 JS 中， 定时器， 动画帧 这些操作， 都是异步操作， 所以是在 回调函数中 处理执行后的内容
        // callback hell： 回调地狱
        // 任务链： 我们的任务可能是一个接着一个的， 而且是有依赖关系的


        // 回调地狱
        // ● 封装简易运动框架
        // ● 最早我们处理异步消息通知，都是通过回调来处理的，
        // 但是回调多了， 代码的结构就必然嵌套层级特别多，
        // 造成可读性和维护性的直线下降 - 这就是回调地狱


        // Promise 对象
        // ES6的Promise对象是一个构造函数（ 通过Promise来构建一个异步任务处理对象）， 
        // 用来生成Promise实例。 所谓Promise对象， 就是代表了未来某个将要发生的事件（ 通常是一个异步操作）。 
        // 它的好处在于， 有了Promise对象， 就可以将异步操作以同步操作的流程表达出来， 避免了层层嵌套的回调函数


        // Promise 基本语法
        // new Promise(function(resolve, reject) {
        // ...要执行的（异步）任务
        /*
         * resolve：函数，当我们调用该函数的时候，可以把当前Promise对象的任务状态该成resolved
         * reject：函数，当我们调用该函数的时候，可以把当前Promise对象的任务状态该成rejected
         * 只要Promise的任务状态发生了变化，这个Promise对象的then方法就会被执行
         */
        // })


        // Promise 内部状态：[[PromiseStatus]]
        // ● Pending 在等待(异步执行中)
        // ● Fulfilled(标准) || Resolved 执行成功 - 调用resolve之后改变
        // ● Rejected 执行失败 - 调用 reject 之后改变


        // Promise.then 方法
        // 任务后续处理函数， 一般情况下处理某个Promise任务完成
        // （ 无论是成功还是失败） 的后续任务
        // promise.then(onFulfilled, onRejected);
        // then方法就是Promise处理完任务以后继续执行的任务


        // 参数：    onFulfilled
        // 当Promise变成接受状态（fulfillment）时，该参数作为回调函数被调用
        // （参考： Function）。该函数有一个参数，即接受的最终结果（the fulfillment  value）。
        // 如果传入的 onFulfilled 参数类型不是函数，则会在内部被替换为(x) => x ，
        // 即原样返回 promise 最终结果的函数

        // 参数：onRejected
        //    当Promise变成拒绝状态（rejection ）时，该参数作为回调函数被调用
        // （参考： Function）。该函数有一个参数,
        // 即拒绝的原因（the rejection reason）。

        // Promise值：[[PromiseValue]]
        // 任务处理完成（成功或失败），返回的值。 
        // 通过 resolve()、reject() 函数传入（例如：resolve(1)、reject(1)）
        // onFulfilled/onResolved, onRejected 函数接收    
        // .then(val=>console.log(val), ...) 
        // resolve, reject这两个函数是可以传入参数的，传入的参数将被传递给then中的函数进行使用



        // Promise Chain 
        // then函数执行后会返回一个新的Promise对象
        // ● 如果then没有传入处理函数，那么会返回一个继承了上一个处理状态的 Promise 对象
        // ● 如果then传入处理函数，那么默认返回一个 fulfilled/resolved 状态的 Promise 对象
        // ● 如果then传入了处理函数，通过处理函数显示的return了一个新的 Promise，
        // 那么返回这个显示的 Promise 对象 
        // 问题：不易中途终止后续任务执行


        //     返回值
        // 当一个Promise完成（fulfilled）或者失败（rejected），返回函数将被异步调用（由当前的线程循环来调度完成）。具体的返回值依据以下规则返回：
        //     - 如果then中的回调函数返回一个值，那么then返回的Promise将会成为接受状态，并且将返回的值作为接受状态的回调函数的参数值。 
        //    - 如果then中的回调函数没有返回值，那么then返回的Promise将会成为接受状态，并且该接受状态的回调函数的参数值为 undefined。 
        //    - 如果then中的回调函数抛出一个错误，那么then返回的Promise将会成为拒绝状态，并且将抛出的错误作为拒绝状态的回调函数的参数值。 
        //    - 如果then中的回调函数返回一个已经是接受状态的Promise，那么then返回的Promise也会成为接受状态，并且将那个Promise的接受状态的回调函数的参数值作为该被返回的Promise的接受状态回调函数的参数值。 
        //    - 如果then中的回调函数返回一个已经是拒绝状态的Promise，那么then返回的Promise也会成为拒绝状态，并且将那个Promise的拒绝状态的回调函数的参数值作为该被返回的Promise的拒绝状态回调函数的参数值。 
        //    - 如果then中的回调函数返回一个未定状态（pending）的Promise，那么then返回Promise的状态也是未定的，并且它的终态与那个Promise的终态相同；同时，它变为终态时调用的回调函数参数与那个Promise变为终态时的回调函数的参数是相同的。

        // let p = new Promise((resolve, reject) => {
        //     // resolve(1)
        //     resolve(2);
        // })
        // let p2 = p.then(
        //     // then方法就是Promise处理完任务以后继续执行的任务
        //     (data) => {
        //         console.log('p的yes');
        //         // return 11
        //         throw Error;
        //     },
        //     (data) => {
        //         console.log('p的no');
        //     }
        // )
        // let p3 = p2.then(
        //     (data) => {
        //         console.log('p2的yes');
        //         console.log(data);
        //     },
        //     (data) => {
        //         console.log('p2的no');
        //         return new Promise((resolve, reject) => {
        //             // resolve(111)
        //             reject(222);
        //         })
        //     }
        // )
        // p3.then((data) => {
        //         console.log('p3的yes');
        //     },
        //     (data) => {
        //         console.log('p3的no');
        //         console.log(data);
        //     })



        // let promise = new Promise((resolve, reject) => {
        //     setTimeout(() => {
        //         resolve(100);
        //     })
        // })

        // promise.then(number => {
        //     console.log('第一个then:' + number);
        //     throw new Error('出错了');
        // }).catch((err) => {
        //     console.log('进入了catch   ' + err);
        //     // throw new Error('出错了');//如果catch里面又抛出一个错误，那么就不走下面的then,直接catch
        // }).then(() => {
        //     console.log('第二个then');
        // }).then(() => {
        //     console.log('第三个then');
        // }).catch(() => {
        //     console.log('又出错了')
        // }).finally(() => {
        //     console.log('最终要做的事情');
        // })










        // 加载图片
        // function getImg(url) {
        //     return new Promise((resolve, reject) => {
        //         // 创建一个图片对象
        //         let img = new Image();
        //         // 监听事件加载成功的事件
        //         img.onload = () => resolve(img);
        //         img.onerror = () => reject(new Error('图片加载失败'));
        //         img.src = url;
        //     })
        // }
        // let pro = getImg('https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fup.enterdesk.com%2Fedpic%2F09%2F3a%2Fbc%2F093abce7b31f4c8ffdbf345375ff4abb.jpg&refer=http%3A%2F%2Fup.enterdesk.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1650890685&t=521725fffba02efd43030711237a213c')
        // pro.then(img => {
        //     document.querySelector('#testImg').src = img.src;
        //     // throw new Error('图片加载失败');
        // }).catch(err => document.write(err))



        // 使用promise封装Ajax
        // https://www.tianqiapi.com/api?version=v9&appid=58858572&appsecret=ka07bqFH
        // XMLHttpRequest来实现Ajax请求
        // function getJson(url) {
        //     return new Promise((resolve, reject) => {
        //         // 1.创建Ajax客户端请求
        //         let client = new XMLHttpRequest();
        //         // 2.设置Ajax请求的参数   POST  DELETE  PUT  GET  增删改查
        //         // 3.springmvc框架中有接受RestFul风格请求的注解
        //         client.open('GET', url);
        //         // 4.设置参数
        //         client.responseType = 'json';
        //         // 5.设置请求内容类型
        //         // application/json
        //         client.setRequestHeader('content-type', 'application/x-www-form-urlencoded')

        //         // 6.监听当前的Ajax请求的状态
        //         client.onreadystatechange = handler;

        //         // 7.发送请求
        //         client.send();
        //         // 监听当前状态的
        //         function handler() {
        //             if (this.readyState !== 4) {
        //                 return;
        //             }
        //             if (this.status == 200) {
        //                 // 请求成功了
        //                 console.log(this);
        //                 resolve(this.response);
        //             } else {
        //                 console.log(this.statusText);
        //             }
        //         }
        //     })
        // }
        // let promise = getJson('https://www.tianqiapi.com/api?version=v9&appid=58858572&appsecret=ka07bqFH');
        // promise.then(resp => console.log(resp)).catch(err => console.log(err))






        // promise处理多个请求
        // 类方法上面有  resolve reject all race..
        // let promise1 = Promise.resolve('hello');
        // let promise2 = Promise.reject('hi');
        // let promise3 = Promise.resolve('world');

        // let promises = Promise.all([promise1, promise2, promise3]);
        // promises.then(data => console.log(data)).catch(err => console.log(err))




        // let promise1 = new Promise((resolve, reject) => {
        //     setTimeout(() => {
        //         resolve('promise1成功执行了');
        //     }, 5000)
        // })
        // let promise2 = new Promise((resolve, reject) => {
        //         setTimeout(() => {
        //             resolve('promise2成功执行了');
        //         }, 2000)
        //     })
        //     // 谁跑得快执行谁
        // let promises = Promise.race([promise1, promise2]);
        // promises.then(data => console.log(data)).catch(err => console.log(err));
    </script>
</body>

</html>